home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / muzsrc1.zip / FILE.CPP < prev    next >
C/C++ Source or Header  |  1992-07-21  |  18KB  |  477 lines

  1. // **********************************************
  2. // File: FILE.CPP
  3. // File menu dialog box functions
  4.  
  5. #include "muzika.h"
  6. #include "dialog.h"
  7. #include <dir.h>
  8. #include <fstream.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. char programTitle[MAXPATH+7] = "MUZIKA "; // Main window caption
  13. char *filepath = programTitle+7;  // Pointer to file path in caption
  14. BOOL melodyModified = FALSE;      // Becomes TRUE whenever melody modified
  15.  
  16. // **********************************************
  17. // AskSave requests the user to confirm qutting
  18. // the current melody after modification. Return TRUE
  19. // if whatever the user requests succeeds (allowing therefore
  20. // to proceed with the previous operation), or FALSE if either
  21. // the user chooses CANCEL or the save fails.
  22.  
  23. BOOL AskSave()
  24. {
  25.   int reply;
  26.  
  27.   // If melody has been modified, display an asking message box
  28.   // and save the melody if the user selects YES
  29.   return melodyModified ?
  30.     ((reply = MessageBox(hMainWnd, "Current melody has been modified. "
  31.       "Do you wish to save it?", "Warning",
  32.       MB_ICONINFORMATION | MB_YESNOCANCEL)) == IDYES) ?
  33.       Save() : (reply == IDNO) : TRUE;
  34. }
  35.  
  36. // **********************************************
  37. // DialogNew is the "File/New..." dialog box function,
  38. // processing messages intended for this dialog box.
  39.  
  40. BOOL FAR PASCAL DialogNew(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  41. {
  42.   static const unsigned widths[]={640-144, 800-144, 1024-144, 0};
  43.  
  44.   switch (message) {
  45.     case WM_INITDIALOG:
  46.       // Process a WM_INITDIALOG message, indicating that
  47.       // the DialogNew function is called for the first time.
  48.       // A list box with the widths list is created.
  49.       for (int index = 0; widths[index]; ++index) {
  50.         char wstr[5];
  51.         itoa(widths[index], wstr, 10);
  52.         SendMessage(GetDlgItem(hDlg, ID_STAFFWIDTH),
  53.           LB_INSERTSTRING, -1, (LONG) wstr);
  54.       }
  55.       SendMessage(GetDlgItem(hDlg, ID_STAFFWIDTH), LB_SETCURSEL, 0, 0);
  56.       return TRUE;
  57.  
  58.     case WM_COMMAND:
  59.       // Process a WM_COMMAND message, indicating that the user
  60.       // has finished making a selection either by pressing OK, CANCEL,
  61.       // or double-clicking the requested width.
  62.       if (wParam == IDOK || HIWORD(lParam) == LBN_DBLCLK) {
  63.         // Set the melody staff width according to what the user selected
  64.         melody.SetStaffWidth(widths[(int)
  65.           SendMessage(GetDlgItem(hDlg, ID_STAFFWIDTH), LB_GETCURSEL, 0, 0)]);
  66.         EndDialog(hDlg, TRUE);
  67.  
  68.         // Initialize the database:
  69.         // create a melody with only one UNNAMED part in it,
  70.         // and reset the various Boolean flags.
  71.         while (melody.part.number())
  72.           melody.part.destroyAt(melody.part.number()-1);
  73.         melodyExists = TRUE;
  74.         melody.part.insertAt(*new Part("UNNAMED", 1), 0);
  75.         scoreDisplay = FALSE;
  76.         displayedPart = 0;
  77.         filepath[0] = 0;
  78.         melodyModified = FALSE;
  79.  
  80.         // Refresh the screen
  81.         SetWindowText(hMainWnd, "MUZIKA (Untitled)");
  82.         InitializeMenu(TRUE);
  83.         SetScrollRange(hEditWnd, SB_VERT, 0, 0, TRUE);
  84.         ShowScrollBar(hEditWnd, SB_VERT, TRUE);
  85.         InvalidateRect(hMainWnd, NULL, TRUE);
  86.         InvalidateRect(hEditWnd, NULL, TRUE);
  87.         IdentifyEditModeSymbol(0x00020002L);
  88.         return TRUE;
  89.       }
  90.  
  91.       if (wParam == IDCANCEL) {
  92.         // The user cancelled the operation:
  93.         // just exit the dialog box without doing anything
  94.         EndDialog(hDlg, FALSE);
  95.         return TRUE;
  96.       }
  97.   }
  98.  
  99.   return FALSE;
  100. }
  101.  
  102. // **********************************************
  103. // LoadError is a generic load error recovery function,
  104. // called whenever there is an error loading a file (probably
  105. // because the file does not conform to MUZIKA format).
  106.  
  107. void LoadError()
  108. {
  109.   // Display an error message box
  110.   SetCursor(LoadCursor(NULL, IDC_ARROW));
  111.   MessageBox(hEditWnd, "The file is not a valid MUZIKA file.", NULL,
  112.     MB_SYSTEMMODAL | MB_OK);
  113.  
  114.   // Delete the currently stored melody
  115.   while (melody.part.number())
  116.     melody.part.destroyAt(melody.part.number()-1);
  117.   melodyExists = FALSE;
  118.   filepath[0] = 0;
  119.   SetWindowText(hMainWnd, "MUZIKA (Untitled)");
  120.   InitializeMenu(FALSE);
  121.   hEditCursor = LoadCursor(NULL, IDC_ARROW);
  122.   ShowScrollBar(hEditWnd, SB_VERT, FALSE);
  123.   InvalidateRect(hMainWnd, NULL, TRUE);
  124.   InvalidateRect(hEditWnd, NULL, TRUE);
  125. }
  126.  
  127. // **********************************************
  128. // DialogOpen is the "File/Open..." dialog box function,
  129. // processing messages intended for this dialog box.
  130.  
  131. BOOL FAR PASCAL DialogOpen(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  132. {
  133.   char path[MAXPATH];
  134.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  135.  
  136.   switch (message) {
  137.     case WM_INITDIALOG:
  138.       // Process a WM_INITDIALOG message, indicating that
  139.       // the DialogOpen function is called for the first time.
  140.       // The file and directory lists are filled.
  141.       DlgDirList(hDlg, "*.MUZ", ID_FILELIST, NULL, 0x0000);
  142.       DlgDirList(hDlg, "*.*", ID_DIRLIST, ID_DIRNAME, 0xC010);
  143.       SetDlgItemText(hDlg, ID_FILENAME, "*.MUZ");
  144.       SendDlgItemMessage(hDlg, ID_FILENAME, EM_SETSEL, NULL, 0x7FFF0000L);
  145.       return TRUE;
  146.  
  147.     case WM_COMMAND:
  148.       // Process a WM_COMMAND message, indicating an action
  149.       // of some kind in the dialog box.
  150.       switch (wParam) {
  151.         case ID_FILELIST:
  152.           switch (HIWORD(lParam)) {
  153.             case LBN_SELCHANGE:
  154.               // The user has made a selection in the file list:
  155.               // respond by copying the selection to the text field
  156.               DlgDirSelect(hDlg, path, ID_FILELIST);
  157.               SetDlgItemText(hDlg, ID_FILENAME, path);
  158.               SendDlgItemMessage(hDlg, ID_FILENAME, EM_SETSEL, NULL, 0x7FFF0000L);
  159.               SendDlgItemMessage(hDlg, ID_DIRLIST, LB_SETCURSEL, -1, NULL);
  160.               break;
  161.  
  162.             case LBN_DBLCLK:
  163.               // The user has double-clicked a selection in the file list:
  164.               // go on and open the file
  165.               goto openfile;
  166.           }
  167.           return TRUE;
  168.  
  169.         case ID_DIRLIST:
  170.           switch(HIWORD(lParam)) {
  171.             case LBN_SELCHANGE:
  172.               // The user has made a selection in the file list:
  173.               // respond by copying the selection to the text field
  174.               DlgDirSelect(hDlg, path, ID_DIRLIST);
  175.               strcat(path, "*.MUZ");
  176.               SetDlgItemText(hDlg, ID_FILENAME, path);
  177.               SendDlgItemMessage(hDlg, ID_FILENAME, EM_SETSEL, NULL, 0x7FFF0000L);
  178.               SendDlgItemMessage(hDlg, ID_FILELIST, LB_SETCURSEL, -1, NULL);
  179.               break;
  180.  
  181.             case LBN_DBLCLK:
  182.               // The user has double-clicked a selection
  183.               // in the directory list:
  184.               // go on and change the directory
  185.               goto openfile;
  186.           }
  187.           return TRUE;
  188.  
  189.         case IDOK:
  190. openfile:
  191.           // This point is reached whenever the user chooses OK
  192.           // or double-clicks a file or directory selection.
  193.           GetDlgItemText(hDlg, ID_FILENAME, path, MAXPATH);
  194.           if (strchr(path, '*')) {
  195.             // The path still contains an '*', meaning that
  196.             // it's not a file name yet:
  197.             // update the file and directory lists
  198.             DlgDirList(hDlg, path, ID_FILELIST, NULL, 0x0000);
  199.             DlgDirList(hDlg, "*.*", ID_DIRLIST, ID_DIRNAME, 0xC010);
  200.             SetDlgItemText(hDlg, ID_FILENAME, "*.MUZ");
  201.             SendDlgItemMessage(hDlg, ID_FILENAME, EM_SETSEL, NULL, 0x7FFF0000L);
  202.           }
  203.           else if (path[0]) {
  204.             // Append a ".MUZ" extension if none given
  205.             if (!(fnsplit(path, drive, dir, file, ext) & EXTENSION))
  206.               strcpy(ext, ".MUZ");
  207.             fnmerge(path, drive, dir, file, ext);
  208.  
  209.             // Check that the file exists
  210.             ifstream in;
  211.             in.open(path, ios::in | ios::nocreate | ios::binary);
  212.             if (in.fail())
  213.               MessageBox(hDlg, "File does not exist.", NULL,
  214.                 MB_ICONEXCLAMATION | MB_OK);
  215.             else {
  216.               // The file exists: close it, and ask if the user
  217.               // wants to save the current melody (in case it
  218.               // has been modified).
  219.               EndDialog(hDlg, TRUE);
  220.               in.close();
  221.               if (!AskSave())
  222.                 return TRUE;
  223.               melodyModified = FALSE;
  224.  
  225.               // Clear the workspace
  226.               while (melody.part.number())
  227.                 melody.part.destroyAt(melody.part.number()-1);
  228.  
  229.               // Use the LoadFrom() virtual function to load the melody
  230.               HCURSOR hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  231.               in.open(path, ios::in | ios::binary);
  232.               if (melody.LoadFrom(in, LoadError)) {
  233.                 // The melody has been successfully loaded:
  234.                 // reset a few Boolean flags and make
  235.                 // part 0 as the displayed part
  236.                 melodyExists = TRUE;
  237.                 strcpy(filepath, path);
  238.                 SetWindowText(hMainWnd, programTitle);
  239.                 InitializeMenu(TRUE);
  240.                 scoreDisplay = FALSE;
  241.                 displayedPart = 0;
  242.                 Part &p = *((Part *) &melody.part[0]);
  243.                 SetScrollRange(hEditWnd, SB_VERT, 0,
  244.                   p.staff.number() ?
  245.                   ((Staff *) &p.staff[p.staff.number()-1])->Y() : 0, TRUE);
  246.                 InvalidateRect(hMainWnd, NULL, TRUE);
  247.                 InvalidateRect(hEditWnd, NULL, TRUE);
  248.                 SetCursor(hPrevCursor);
  249.               }
  250.             }
  251.             in.close();
  252.           }
  253.           return TRUE;
  254.  
  255.         case IDCANCEL:
  256.           // The user cancelled the operation:
  257.           // just exit the dialog box without doing anything
  258.           EndDialog(hDlg, FALSE);
  259.           return TRUE;
  260.       }
  261.   }
  262.  
  263.   return FALSE;
  264. }
  265.  
  266. // **********************************************
  267. // Save saves the current melody, asking for a file name
  268. // (i.e. calling SaveAs) if no current file name exists.
  269.  
  270. BOOL Save()
  271. {
  272.   ofstream out;
  273.  
  274.   if (filepath[0]) {
  275.     // The melody already has a file name:
  276.     // open the stream and use Melody::printOn to save the melody
  277.     HCURSOR hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  278.     out.open(filepath, ios::out | ios::binary);
  279.     melody.printOn(out);
  280.     out.close();
  281.     melodyModified = FALSE;
  282.     SetCursor(hPrevCursor);
  283.     return TRUE;
  284.   }
  285.   else {
  286.     // No current file name:
  287.     // open a "Save As..." dialog box
  288.     FARPROC lpDialog = MakeProcInstance((FARPROC) DialogSaveAs, hInst);
  289.     BOOL saved = DialogBox(hInst, "D_FILESAVEAS", hMainWnd, lpDialog);
  290.     FreeProcInstance(lpDialog);
  291.     return saved;
  292.   }
  293. }
  294.  
  295. // **********************************************
  296. // DialogSaveAs is the "File/Save As..." dialog box function,
  297. // processing messages intended for this dialog box.
  298.  
  299. BOOL FAR PASCAL DialogSaveAs(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  300. {
  301.   char path[MAXPATH];
  302.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  303.  
  304.   switch (message) {
  305.     case WM_INITDIALOG:
  306.       // Process a WM_INITDIALOG message, indicating that
  307.       // the DialogSaveAs function is called for the first time.
  308.       // The directory list is filled.
  309.       DlgDirList(hDlg, "*.*", ID_DIRLIST, ID_DIRNAME, 0xC010);
  310.       return TRUE;
  311.  
  312.     case WM_COMMAND:
  313.       // Process a WM_COMMAND message, indicating an action
  314.       // of some kind in the dialog box.
  315.       switch (wParam) {
  316.         case ID_DIRLIST:
  317.           switch(HIWORD(lParam)) {
  318.             case LBN_SELCHANGE:
  319.               // The user has selected a directory:
  320.               // respond by copying the selection to the text field
  321.               DlgDirSelect(hDlg, path, ID_DIRLIST);
  322.               SetDlgItemText(hDlg, ID_FILENAME, path);
  323.               SendDlgItemMessage(hDlg, ID_FILENAME, EM_SETSEL, NULL, 0x7FFF0000L);
  324.               break;
  325.  
  326.             case LBN_DBLCLK:
  327.               // The user has double-clicked a directory:
  328.               // go on and update the directory list
  329.               goto savefile;
  330.           }
  331.           return TRUE;
  332.  
  333.         case IDOK:
  334. savefile:
  335.        // This point is reached when the user selects OK
  336.           // or double-clicks a directory selection.
  337.           GetDlgItemText(hDlg, ID_FILENAME, path, MAXPATH);
  338.           if (path[strlen(path)-1] == ':' || path[strlen(path)-1] == '\\') {
  339.             // The text field ends with a ':' or '\\', meaning
  340.             // that no file name has been selected yet:
  341.             // refill the directory list box
  342.             DlgDirList(hDlg, path, ID_DIRLIST, ID_DIRNAME, 0xC010);
  343.             SetDlgItemText(hDlg, ID_FILENAME, "");
  344.           }
  345.           else if (path[0]) {
  346.             // Append a ".MUZ" extension to the file name if necessary
  347.             if (!(fnsplit(path, drive, dir, file, ext) & EXTENSION))
  348.               strcpy(ext, ".MUZ");
  349.             fnmerge(path, drive, dir, file, ext);
  350.  
  351.             // Check if the file already exists
  352.             ofstream out;
  353.             out.open(path, ios::out | ios::noreplace | ios::binary);
  354.             if (out.fail())
  355.               // The file already exists:
  356.               // confirm that it should be overwritten
  357.               if (MessageBox(hDlg, "File already exists. Overwrite?",
  358.                 "Warning", MB_ICONINFORMATION | MB_YESNOCANCEL) != IDYES) {
  359.                 out.close();
  360.                 return TRUE;
  361.               }
  362.             out.close();
  363.             HDC hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));;
  364.             out.open(path, ios::out | ios::trunc | ios::binary);
  365.             EndDialog(hDlg, TRUE);
  366.  
  367.             // Use the printOn() virtual function to save the melody
  368.             melody.printOn(out);
  369.             out.close();
  370.             melodyModified = FALSE;
  371.             strcpy(filepath, path);
  372.             SetWindowText(hMainWnd, programTitle);
  373.             SetCursor(hPrevCursor);
  374.           }
  375.           return TRUE;
  376.  
  377.         case IDCANCEL:
  378.           // The user cancelled the operation:
  379.           // exit the dialog box without doing anything
  380.           EndDialog(hDlg, FALSE);
  381.           return TRUE;
  382.       }
  383.   }
  384.  
  385.   return FALSE;
  386. }
  387.  
  388. // **********************************************
  389. // DialogCreateMIDI is the "File/Create MIDI..." dialog box function,
  390. // processing message intended for this dialog box.
  391.  
  392. BOOL FAR PASCAL DialogCreateMIDI(HWND hDlg, unsigned message, WORD wParam, LONG lParam)
  393. {
  394.   char path[MAXPATH];
  395.   char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  396.  
  397.   switch (message) {
  398.     case WM_INITDIALOG:
  399.       // Process a WM_INITDIALOG message, indicating that the
  400.       // DialogCreateMIDI function is called for the first time.
  401.       // The directory list is filled.
  402.       DlgDirList(hDlg, "*.*", ID_DIRLIST, ID_DIRNAME, 0xC010);
  403.       return TRUE;
  404.  
  405.     case WM_COMMAND:
  406.       // Process a WM_COMMAND message, indicating an action
  407.       // of some kind in the dialog box.
  408.       switch (wParam) {
  409.         case ID_DIRLIST:
  410.           switch(HIWORD(lParam)) {
  411.             case LBN_SELCHANGE:
  412.               // The user has selected a directory:
  413.               // respond by copying the selection to the text field
  414.               DlgDirSelect(hDlg, path, ID_DIRLIST);
  415.               SetDlgItemText(hDlg, ID_FILENAME, path);
  416.               SendDlgItemMessage(hDlg, ID_FILENAME, EM_SETSEL, NULL, 0x7FFF0000L);
  417.               break;
  418.  
  419.             case LBN_DBLCLK:
  420.               // The user has double-clicked a directory selection:
  421.               // go on and update the directory list
  422.               goto savefile;
  423.           }
  424.           return TRUE;
  425.  
  426.         case IDOK:
  427. savefile:
  428.           // This point is reached when the user selects OK
  429.           // or double-clicks a directory selection.
  430.           GetDlgItemText(hDlg, ID_FILENAME, path, MAXPATH);
  431.           if (path[strlen(path)-1] == ':' || path[strlen(path)-1] == '\\') {
  432.             // The text field ends with ':' or '\\', meaning
  433.             // that no file has been selected yet:
  434.             // refill the directory list box
  435.             DlgDirList(hDlg, path, ID_DIRLIST, ID_DIRNAME, 0xC010);
  436.             SetDlgItemText(hDlg, ID_FILENAME, "");
  437.           }
  438.           else if (path[0]) {
  439.             // Append a ".MUZ" extension if necessary
  440.             if (!(fnsplit(path, drive, dir, file, ext) & EXTENSION))
  441.               strcpy(ext, ".MID");
  442.             fnmerge(path, drive, dir, file, ext);
  443.  
  444.             // Check if the file already exists
  445.             ofstream out;
  446.             out.open(path, ios::out | ios::noreplace | ios::binary);
  447.             if (out.fail())
  448.               // The file already exists:
  449.               // confirm that the user wants it overwritten
  450.               if (MessageBox(hDlg, "File already exists. Overwrite?",
  451.                 "Warning", MB_ICONINFORMATION | MB_YESNOCANCEL) != IDYES) {
  452.                 out.close();
  453.                 return TRUE;
  454.               }
  455.             out.close();
  456.             HDC hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));;
  457.             out.open(path, ios::out | ios::trunc | ios::binary);
  458.             EndDialog(hDlg, TRUE);
  459.  
  460.             // Create the MIDI file
  461.             CreateMIDIFile(out);
  462.             out.close();
  463.             SetCursor(hPrevCursor);
  464.           }
  465.           return TRUE;
  466.  
  467.         case IDCANCEL:
  468.           // The user cancelled the operation:
  469.           // exit the dialog box without doing anything
  470.           EndDialog(hDlg, FALSE);
  471.           return TRUE;
  472.       }
  473.   }
  474.  
  475.   return FALSE;
  476. }
  477.